package com.ruiysoft.service.logistics;

import com.alibaba.fastjson.JSON;
import com.ruiysoft.conf.logistics.LogisticsConfig;
import com.ruiysoft.entity.logistics.*;
import com.ruiysoft.entity.logistics.kuaidi100.Kuaidi100Config;
import com.ruiysoft.entity.logistics.kuaidi100.Kuaidi100Exception;
import com.ruiysoft.entity.logistics.kuaidi100.Kuaidi100MD5Tool;
import com.ruiysoft.pub.core.Result;
import com.ruiysoft.pub.core.ResultCode;
import com.ruiysoft.util.HttpConnManager;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 通过@Bean定义
 * 关于 URL_CALLBACK
 * @see com.ruiysoft.controller.logistics.LogisticsApi
 * @see LogisticsConfig
 */
public class Kuaidi100Caller implements IExpressCaller<Kuaidi100Config> {
    private Logger logger = LoggerFactory.getLogger(Kuaidi100Caller.class);

	public final static String API_SUPPLIER = "kuaidi100";

	private final static String URL_QUERY_COMPANY = "http://www.kuaidi100.com/autonumber/auto";
	private final static String URL_QUERY_EXPRESS = "http://poll.kuaidi100.com/poll/query.do";
	private final static String URL_SUBSCRIBE = "https://poll.kuaidi100.com/poll";
	private final String URL_CALLBACK;

	public Kuaidi100Caller(String baseCallBackURL){
        /**
         @see
         */
        URL_CALLBACK = baseCallBackURL+"/logistics/callback"+"/"+API_SUPPLIER;
    }

	@Override
	public final String getAPISupplier(){
		return API_SUPPLIER;
	}

    @Override
    public Class getConfigClass() {
        return Kuaidi100Config.class;
    }

	/*@Autowired
    @Qualifier(LogisticsConfig.BEAN_REST_TEMPLATE_FOR_THIRD_KUAIDI100)
	RestTemplate restTemplate;*/


    @Override
    @Async
    public Result<String> subscribe(Long shopID,Kuaidi100Config logisticsConfig, String expressCom, String expressNO) {

        SubscribeMainParam mainParam = new SubscribeMainParam();
        mainParam.setCompany(expressCom);
        mainParam.setNumber(expressNO);
        mainParam.setKey(logisticsConfig.getKey());

        QueryParam qp = new QueryParam(expressCom,expressNO);
        String param = JSON.toJSONString(qp);
        String customer = logisticsConfig.getCustomer();
        String sign = Kuaidi100MD5Tool.encode(param+logisticsConfig.getKey()+customer);

        SubscribeDeatilParam deatilParam = new SubscribeDeatilParam();
        deatilParam.setCallbackurl(URL_CALLBACK+"/"+shopID);
        deatilParam.setAutoCom("1");//表示开始智能判断单号所属公司的功能
        deatilParam.setInterCom("1");//添加此字段表示开启国际版
        deatilParam.setSalt(sign);
        //deatilParam.setDepartureCountry("CN");//出发国家编码
        //deatilParam.setDepartureCom("ems");
        //deatilParam.setDestinationCountry("JP");
        //deatilParam.setDepartureCom("japanposten");
        mainParam.setParameters(deatilParam);

        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        nvps.add(new BasicNameValuePair("schema", "json"));
        nvps.add(new BasicNameValuePair("param", JSON.toJSONString(mainParam)));
        Result<String> result = new Result<String>();
        try {
            CloseableHttpClient httpclient = HttpConnManager.getInstance().getHttpClient();
            HttpPost httpPost = new HttpPost(URL_SUBSCRIBE);
            httpPost.setEntity(new UrlEncodedFormEntity(nvps));
            //向服务端发送报文
            CloseableHttpResponse response = httpclient.execute(httpPost);
            //获得服务端返回值
            String respMessage = EntityUtils.toString(response.getEntity(), "utf-8");

            result.setBizCode(ResultCode.CODE_SUCCESS);
            result.setBizMessage(respMessage);
        }catch (IOException e){
            result.setBizMessage(ResultCode.CODE_COMMON_ERROR);
            result.setBizMessage(e.getMessage());
            logger.error("快递100订阅错.",e);
        }
        return result;
    }

    @Override
	public Optional<List<? extends APIExpressCompany>>  queryExpressCompByExpressNO(Kuaidi100Config kuaidi100Config,String expressNO) throws Kuaidi100Exception {

        String queryStr = String.format("?num=%s&key=%s",expressNO,kuaidi100Config.getKey());
        /*
        RestTemplate 方式
        ResponseEntity<byte[]> responseEntity = restTemplate.exchange(URL_QUERY_COMPANY + queryStr, HttpMethod.GET,null,byte[].class);
        if(responseEntity.getStatusCodeValue() != 200){
            throw new Kuaidi100NotMachExpressException("无法查询快递API,Http Response code:"+responseEntity.getStatusCodeValue() );
        }
        responseEntity.getBody();
        String respMessage =  new String(responseEntity.getBody(), Charset.forName("utf-8"));
        return Optional.of(JSON.parseArray(respMessage, APIExpressCompany.class));*/

        /*Apache HttpClient*/
        try {
            CloseableHttpClient httpclient = HttpConnManager.getInstance().getHttpClient();
            HttpGet httpGet = new HttpGet(URL_QUERY_COMPANY + queryStr);
            CloseableHttpResponse response = httpclient.execute(httpGet);
            //获得服务端返回值
            String respMessage = EntityUtils.toString(response.getEntity(), "utf-8");
            return Optional.of(JSON.parseArray(respMessage, APIExpressCompany.class));
        }catch (IOException e){
            throw new Kuaidi100Exception("无法查询快递API",e);
        }
	}

	@Override
	public  Optional<APILogisticsMessage> queryExpress(Kuaidi100Config kuaidi100Config,String expressNO) throws Kuaidi100Exception {

		Optional<List<? extends APIExpressCompany>>  apiExpressCompanies = queryExpressCompByExpressNO(kuaidi100Config,expressNO);
		List<? extends APIExpressCompany> list = apiExpressCompanies.get();
		for (APIExpressCompany comp : list) {
			Optional<APILogisticsMessage> optionalAPILogisticsMessage = queryExpress(kuaidi100Config, expressNO, comp.getComCode());
			Boolean b = optionalAPILogisticsMessage.map(h->Boolean.TRUE.equals(h.isResult())).orElse(false);
			if(b){
				return optionalAPILogisticsMessage;
			}
		}
		return Optional.empty();

	}


	@Override
	public  Optional<APILogisticsMessage> queryExpress(Kuaidi100Config kuaidi100Config,String expressNO,String expressCom) throws Kuaidi100Exception {
		QueryParam qp = new QueryParam(expressNO,expressCom);
		String param = JSON.toJSONString(qp);
		String customer = kuaidi100Config.getCustomer();
		String sign = Kuaidi100MD5Tool.encode(param+kuaidi100Config.getKey()+customer);
		try {
			CloseableHttpClient httpclient = HttpConnManager.getInstance().getHttpClient();
			HttpPost httpPost = new HttpPost(URL_QUERY_EXPRESS);
			/*
			httpPost.setHeader("Content-Type","application/json; charset=utf-8");
			httpPost.setHeader("Accept", "application/json");
			StringEntity reqByteEntity = new StringEntity("","");
			reqByteEntity.setContentType("application/json; charset=utf-8");
			*/
			List<NameValuePair> nvps = new ArrayList<NameValuePair>();
			nvps.add(new BasicNameValuePair("param", param));
			nvps.add(new BasicNameValuePair("customer", customer));
			nvps.add(new BasicNameValuePair("sign", sign));
			httpPost.setEntity(new UrlEncodedFormEntity(nvps));
			//向服务端发送报文
			CloseableHttpResponse response = httpclient.execute(httpPost);
			//获得服务端返回值
			String respMessage = EntityUtils.toString(response.getEntity(),"utf-8");
            Optional<APILogisticsMessage> logisticsMessage = Optional.ofNullable(JSON.parseObject(respMessage, APILogisticsMessage.class));
            if(logisticsMessage.isPresent()) {
                logisticsMessage.get().setComCode(expressCom);
                logisticsMessage.get().setExpressNO(expressNO);
            }
            return logisticsMessage;
		}catch (IOException e){
			throw new Kuaidi100Exception("网络错误，无法查询快递100",e);
		}
	}

	private static class QueryParam{
		private String com;
		private String num;

		public QueryParam(String num,String com) {
			super();
			this.com = com;
			this.num = num;
		}
		public String getCom() {
			return com;
		}
		public void setCom(String com) {
			this.com = com;
		}
		public String getNum() {
			return num;
		}
		public void setNum(String num) {
			this.num = num;
		}
	}


    private static class SubscribeMainParam {

        private String company;
        private String number;
        private String from;
        private String to;
        private String key;
        private SubscribeDeatilParam parameters;
        public void setCompany(String company) {
            this.company = company;
        }
        public String getCompany() {
            return company;
        }

        public void setNumber(String number) {
            this.number = number;
        }
        public String getNumber() {
            return number;
        }

        public void setFrom(String from) {
            this.from = from;
        }
        public String getFrom() {
            return from;
        }

        public void setTo(String to) {
            this.to = to;
        }
        public String getTo() {
            return to;
        }

        public void setKey(String key) {
            this.key = key;
        }
        public String getKey() {
            return key;
        }

        public void setParameters(SubscribeDeatilParam parameters) {
            this.parameters = parameters;
        }
        public SubscribeDeatilParam getParameters() {
            return parameters;
        }

    }

    private static class SubscribeDeatilParam {

        private String callbackurl;
        private String salt;
        private String resultv2;
        private String autoCom;
        private String interCom;
        private String departureCountry;
        private String departureCom;
        private String destinationCountry;
        private String destinationCom;
        public void setCallbackurl(String callbackurl) {
            this.callbackurl = callbackurl;
        }
        public String getCallbackurl() {
            return callbackurl;
        }

        public void setSalt(String salt) {
            this.salt = salt;
        }
        public String getSalt() {
            return salt;
        }

        public void setResultv2(String resultv2) {
            this.resultv2 = resultv2;
        }
        public String getResultv2() {
            return resultv2;
        }

        public void setAutoCom(String autoCom) {
            this.autoCom = autoCom;
        }
        public String getAutoCom() {
            return autoCom;
        }

        public void setInterCom(String interCom) {
            this.interCom = interCom;
        }
        public String getInterCom() {
            return interCom;
        }

        public void setDepartureCountry(String departureCountry) {
            this.departureCountry = departureCountry;
        }
        public String getDepartureCountry() {
            return departureCountry;
        }

        public void setDepartureCom(String departureCom) {
            this.departureCom = departureCom;
        }
        public String getDepartureCom() {
            return departureCom;
        }

        public void setDestinationCountry(String destinationCountry) {
            this.destinationCountry = destinationCountry;
        }
        public String getDestinationCountry() {
            return destinationCountry;
        }

        public void setDestinationCom(String destinationCom) {
            this.destinationCom = destinationCom;
        }
        public String getDestinationCom() {
            return destinationCom;
        }

    }


}
